package com.dhgate.spu.analysis.collector;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.dhgate.spu.analysis.bean.Product;
import com.dhgate.spu.analysis.consts.CommonConsts;
import com.dhgate.spu.analysis.consts.SysConsts;
import com.dhgate.spu.analysis.util.CommonUtil;
import com.dhgate.spu.analysis.util.ComparatorUtil;
import com.dhgate.spu.analysis.util.StringUtil;

/**
 * @author: wangguodong
 * @create: 2014-3-6 下午5:10:19
 * @description:
 */
public class PhoneCollector extends StandardCollector {

	private static final Logger logger = LoggerFactory.getLogger(PhoneCollector.class);
	public static String BRAND_MODEL_FILE_PATH = SysConsts.BASE_DIR + "brand-model.txt";

	private static final List<String> PHONE_CPU_CHIP_MODEL_LIST = new ArrayList<String>();

	private static final Pattern RAM_GB_PATTERN = Pattern.compile("(\\d+)gb{0,1} ram");
	private static final Pattern RAM_MB_PATTERN = Pattern.compile("(\\d+)mb{0,1} ram");
	private static final Pattern GB_PATTERN = Pattern.compile(" (\\d+)gb{0,1} ");
	private static final Pattern MB_PATTERN = Pattern.compile(" (\\d+)mb{0,1} ");

	private static long PHONE_CHINESE_BRAND_ATTR_ID = 843500L;
	// private static long PHONE_CHINESE_BRAND_NO_BRAND_ID=1404540L;
	public static String PHONE_ATTR_VAL_IDS = "";

	// 国产手机品牌和型号的对应关系 key：品牌id, value：型号list
	private static Map<String, List<String>> BRANDID_MODEL_MAP = new HashMap<String, List<String>>();
	// 国产品牌id=>英文名对应的map
	private static Map<String, String> ENNAME_BRANDID_MAP = new HashMap<String, String>();
	// 品牌id列表
	private static List<String> BRAND_ENNAME_LIST = new ArrayList<String>();

	public void init() throws Exception {
		logger.info("init begin");
		initBrandModel(BRAND_MODEL_FILE_PATH);
		initCpuChipModelList();
		logger.info("init end ENNAME_BRANDID_MAP.size" + ENNAME_BRANDID_MAP.size());
	}

	private void initCpuChipModelList() {
		String chipModelArray[] = {
				// Qualcomm高通
				"qualcomm800", "qualcomm805", "msm8225q", "msm8225", "qualcomm600", "qualcomm602A", "qualcomm400", "qualcomm410", "qualcomm200", "s3", "s2", "s1",
				// Spreadtrum展讯
				"SC9610", "SC8815", "SC7715", "SC5735A", "SC8735S", "SC8835S", "SC7735S", "SC8830A", "SC7730A", "SC8825", "SC8810", "SC7710", "SC7701B", "SC8800G", "SC8801G", "SC8802G", "SC6815", "SC6825", "SC6820", "SC6531", "SC6530",
				// MTK联发科
				"mt6572", "mtk6572", "mt6573", "mtk6573", "mt6573", "mtk6573", "mt6577", "mtk6577", "mt6589", "mtk6589", "mt6572W", "mtk6572W", "mt6589T", "mtk6589T", "mt6592", "mtk6592", "mt6732", "mtk6732", "mt6732", "mtk6732", "mt6276M", "mtk6276M", "mt6268", "mtk6268",
				"mt6255", "mtk6255", "mt6253", "mtk6253", "mt6252", "mtk6252", "mt6239", "mtk6239", "mt6238", "mtk6238", "mt6236", "mtk6236", "mt6235", "mtk6235", "mt6223", "mtk6223", };
		for (String chipModel : chipModelArray) {
			PHONE_CPU_CHIP_MODEL_LIST.add(chipModel.toLowerCase());
		}
		Collections.sort(PHONE_CPU_CHIP_MODEL_LIST, ComparatorUtil.STR_LENGTH_COMPARATOR);
	}

	private void initBrandModel(String filePath) throws Exception {
		Map<String, List<String>> brandModelMap = new HashMap<String, List<String>>();
		Map<String, String> ennameBrandIdMap = new HashMap<String, String>();
		List<String> brandEnNameList = new ArrayList<String>();

		InputStreamReader fr;
		try {
			fr = new InputStreamReader(new FileInputStream(filePath));

			BufferedReader br = new BufferedReader(fr);
			String line = br.readLine();
			while (line != null) {
				line = line.toLowerCase();
				if (StringUtil.isEmpty(line)) {
					line = br.readLine();
					continue;
				}
				String array[] = line.split(":");
				String brandAttrValId = array[0].trim();
				String brandEnName = array[1].trim();
				brandEnNameList.add(brandEnName);
				ennameBrandIdMap.put(brandEnName, brandAttrValId);

				if (array.length >= 4) {
					String modelArray[] = array[3].split(",");
					List<String> modelList = new ArrayList<String>();
					brandModelMap.put(brandAttrValId, modelList);
					Map<String, String> modelMap = new HashMap<String, String>();
					for (String model : modelArray) {
						if (!modelMap.containsKey(model)) {
							modelList.add(model);
						}
						modelMap.put(model, model);
					}
					Collections.sort(modelList, ComparatorUtil.STR_LENGTH_COMPARATOR);
					logger.debug("brandId: " + brandAttrValId + ",brandName: " + array[1] + ", model size=" + modelList.size());
				} else {
					logger.warn(" not get model line:" + line);
				}

				line = br.readLine();
			}
			br.close();
		} catch (Exception e) {
			logger.error("readFile " + filePath + " error:" + e);
			e.printStackTrace();
			throw new Exception("readFile " + filePath + " error:" + e);
		}
		Collections.sort(brandEnNameList, ComparatorUtil.STR_LENGTH_COMPARATOR);
		BRANDID_MODEL_MAP = brandModelMap;
		ENNAME_BRANDID_MAP = ennameBrandIdMap;
		BRAND_ENNAME_LIST = brandEnNameList;
	}

	@Override
	public void process(Product p) {
		super.process(p);
	}

	protected void regulateProduct(Product p) {
		String regProductName = p.getProductName().toLowerCase();
		String partNameArray[] = regProductName.split(" ");
		Set<String> partNameSet = new HashSet<String>();
		for (String partName : partNameArray) {
			partNameSet.add(partName.trim());
		}

		fillBrandAndRamId(p);
		xtractField(p, regProductName, partNameSet);

	}

	private void xtractField(Product p, String regProductName, Set<String> partNameSet) {
		xtractBrand(p, regProductName, partNameSet);
		xtractModel(p, regProductName, partNameSet);
		xtractChipModel(p, partNameSet);
		// xtractRam(p, regProductName);
	}

	private static void fillBrandAndRamId(Product p) {
		if (p.getAttrMap() == null || p.getAttrMap().size() == 0) {
			return;
		}

		List<Long> brandAttrValList = p.getAttrValIdList(PHONE_CHINESE_BRAND_ATTR_ID);
		if (brandAttrValList != null && brandAttrValList.size() > 0) {
			long lBrandId = brandAttrValList.get(0);
			p.setField(CommonConsts.FieldName.BRAND_ID, lBrandId + "");
		}

	}

	// 1.标题+品牌导出品牌 2.标题+品牌中的型号导出品牌
	private void xtractBrand(Product p, String regProductName, Set<String> partNameSet) {
		if (StringUtil.isNotEmpty(p.getField(CommonConsts.FieldName.BRAND_ID))) {
			return;// 如果已经有品牌了就不用抽取了
		}

		List<String> extBrandByBrandList = new ArrayList<String>();
		List<String> extBrandByModelList = new ArrayList<String>();

		for (String brandEnname : BRAND_ENNAME_LIST) {
			// 1.标题+品牌导出品牌
			if (partNameSet.contains(brandEnname)) {
				extBrandByBrandList.add(brandEnname);
			}
			String brandId = ENNAME_BRANDID_MAP.get(brandEnname);

			// 2.标题+品牌中的型号导出品牌
			List<String> modelList = BRANDID_MODEL_MAP.get(brandId);
			String model = xtractKeyword(modelList, regProductName, partNameSet);
			if (StringUtil.isNotEmpty(model)) {
				extBrandByModelList.add(brandEnname);
			}
		}

		if (extBrandByBrandList.size() == 0 && extBrandByModelList.size() == 0) {
			return;
		}

		String extBrandEnname = null;
		// 1.求两个list的交集的第一个作为抽取的品牌
		List<String> interList = CommonUtil.getInterList(extBrandByBrandList, extBrandByModelList);
		if (interList.size() > 0) {
			extBrandEnname = interList.get(0);
		}

		// 2.否则求extBrandByBrandList第一个作为抽取的品牌
		if (extBrandEnname == null && extBrandByBrandList.size() > 0) {
			extBrandEnname = extBrandByBrandList.get(0);
		}

		if (extBrandEnname != null) {
			String strBrandValId = ENNAME_BRANDID_MAP.get(extBrandEnname);
			if (strBrandValId == null) {
				return;
			}

			List<Long> attrValIdList = new ArrayList<Long>();
			attrValIdList.add(Long.parseLong(strBrandValId));
			//添加新的品牌id
			p.addAttrValIdSet(Long.parseLong(strBrandValId));
			//清理无效的品牌id
			p.removeAttrValIdSet(1404540L);
			p.setAttrValIdList(PHONE_CHINESE_BRAND_ATTR_ID, attrValIdList);
			p.setField(CommonConsts.FieldName.BRAND_ID, strBrandValId);
		}
	}

	private void xtractModel(Product p, String productName, Set<String> partNameSet) {
		String model = xtractKeyword(BRANDID_MODEL_MAP.get(p.getField(CommonConsts.FieldName.BRAND_ID)), productName, partNameSet);
		if (StringUtil.isEmpty(model)) {
			return;
		}
		p.setExtField(CommonConsts.ExtFieldName.MODEL, model);
	}

	private void xtractChipModel(Product p, Set<String> partNameSet) {
		String chipModel = xtractKeyword(PHONE_CPU_CHIP_MODEL_LIST, "", partNameSet);

		if (StringUtil.isEmpty(chipModel)) {
			return;
		}

		p.setExtField(CommonConsts.ExtFieldName.CHIP_MODEL, chipModel);
	}

	// TODO 如果使用导出的RAM则需要将ram的attrValId设置到product上
	private void xtractRam(Product p, String regProductName) {

		String ramName = null;
		// 1. 按照GB RAM匹配
		Matcher matcher = RAM_GB_PATTERN.matcher(regProductName);
		if (matcher.find()) {
			int intFindRam = Integer.parseInt(matcher.group(1));
			if (isVaildGbRam(intFindRam)) {
				ramName = intFindRam + "g";
			}
		}

		// 2. 按照MB RAM匹配
		if (ramName == null) {
			matcher = RAM_MB_PATTERN.matcher(regProductName);
			if (ramName == null && matcher.find()) {
				int intFindRam = Integer.parseInt(matcher.group(1));
				if (isVaildMbRam(intFindRam)) {
					ramName = intFindRam + "g";
				}
			}
		}

		// 3. 按照GB匹配
		if (ramName == null) {
			matcher = GB_PATTERN.matcher(regProductName);
			int intRam = 0;//
			// 循环取匹配到的最小的
			while (matcher.find()) {
				int findRam = Integer.parseInt(matcher.group(1));
				boolean isVaildGbRam = isVaildGbRam(findRam);
				if (intRam == 0 && isVaildGbRam) {
					intRam = findRam;
				}
				if (isVaildGbRam && findRam < intRam) {
					intRam = findRam;
				}
			}
			if (intRam > 0) {
				ramName = intRam + "g";
			}
		}

		// 4. 按照MB匹配
		if (ramName == null) {
			matcher = MB_PATTERN.matcher(regProductName);
			int intRam = 0;//
			// 获取到第一个合格的即可(MB大小数字比较固定,没有ROM做捣乱)
			while (matcher.find()) {
				int findRam = Integer.parseInt(matcher.group(1));
				if (isVaildMbRam(findRam)) {
					intRam = findRam;
					break;
				}
			}
			if (intRam > 0) {
				ramName = intRam + "m";
			}
		}

	}

	private boolean isVaildGbRam(int ram) {
		return CommonConsts.RamValue.GB_RAM_SET.contains(ram + "");
	}

	private boolean isVaildMbRam(int ram) {
		return CommonConsts.RamValue.MB_RAM_SET.contains(ram + "");
	}

}